package com.hc.comm.utils;

import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.ServletRequestDataBinder;

import com.hc.comm.session.ISessionService;
import com.hc.comm.session.SessionServiceFactory;
import com.hc.comm.session.SessionServiceFactory.SessionTypeEnum;
import com.hc.comm.utils.Constant.ContentTypeEnum;
import com.hc.comm.utils.Constant.HttpScopeEnum;
import com.hc.comm.utils.Constant.PropertiesFileEnum;



/**
 * web工具类
 * 
 * @author 
 * @date 
 */
public class ServletUtil {

	@SuppressWarnings("unused")
	private static Logger logger = Logger.getLogger(ServletUtil.class);

	/**
	 * 标志ajax请求的参数名称
	 */
	public static final String ISAJAX = "isajax";

	/**
	 * 标志jsonp回调函数的参数名称
	 */
	public static final String JSONP_CALLBACK = "callback";

	/**
	 * 资源文件中session失效时间对应的key
	 */
	public static final String SESSION_TIME_OUT = "SESSION_TIME_OUT";

	/**
	 * 保存在request中的操作结果的键的名称
	 */
	public final static String OPERATERESULT_REQUEST = "operateResult";

	/**
	 * 保存在request中的操作异常的键的名称
	 */
	public final static String OPERATEEXCEPTIONINFO_REQUEST = "OPERATEEXCEPTIONINFO_REQUEST";

	/**
	 * 用户在session中的信息的key
	 */
	public final static String USER_SESSION = "USER_SESSION";

	/**
	 * 每页显示最大数据量
	 */
	public final static int maxPageSize = 200;

	/**
	 * session默认失效时间(秒)，获取session的失效时间都通过getSessionTimeOut方法获取
	 */
	private static int sessionTimeOut = 10;

	/**
	 * sessionid 名称
	 */
	public final static String SESSION_ID = "YJD_SESSION_ID";
	/**
	 * session获取标志
	 */
	private static boolean sessionTimeFlag = true;

	/**
	 * springmvc请求后缀在web.properties中的key
	 */
	public final static String URLSTUFFKEY = "urlStuff";

	/**
	 * 获取某种范围(request,session,applicatioin)的值
	 * 
	 * @param key
	 * @param scope
	 * @return
	 */
	public static Object getValueFormScope(HttpServletRequest request,
			HttpServletResponse response, String key, HttpScopeEnum scope) {
		if (scope == HttpScopeEnum.REQUEST) {
			return request.getAttribute(key);
		} else if (scope == HttpScopeEnum.SESSION) {
			return getSession(request, response, key);
		} else if (scope == HttpScopeEnum.APPLICATION) {
			return request.getSession().getServletContext().getAttribute(key);
		}
		return null;
	}

	/**
	 * 
	 * 向某种范围(request,session.applicatioin)中存入值
	 * 
	 * @param key
	 * @param scope
	 * @return
	 */
	public static void putValueToScope(HttpServletRequest request,
			HttpServletResponse response, String key, Object value,
			HttpScopeEnum scope) {
		if (scope == HttpScopeEnum.REQUEST) {
			request.setAttribute(key, value);
		} else if (scope == HttpScopeEnum.SESSION) {
			putSession(request, response, key, value);
		} else if (scope == HttpScopeEnum.APPLICATION) {
			request.getSession().getServletContext().setAttribute(key, value);
		}
	}

	/**
	 * 获取request中参数的集合,如果有多个值的对于只取其中一个
	 * 
	 * @return
	 */
	public static Map<Object, Object> getParameterMap(HttpServletRequest request) {
		return getParameterMap(request, false);
	}

	/**
	 * 获取request中参数集合，如果有多个值的，获取的是数组
	 * 
	 * @param request
	 * @param isParams
	 *            多个值的是否是数组
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static Map<Object, Object> getParameterMap(
			HttpServletRequest request, boolean isParams) {
		Map<Object, Object> parameterMap = new HashMap<Object, Object>();
		Enumeration<String> parameternames = request.getParameterNames();
		while (parameternames.hasMoreElements()) {
			String name = (String) parameternames.nextElement();
			parameterMap.put(name, isParams ? request.getParameterValues(name)
					: request.getParameter(name));
		}
		return parameterMap;
	}

	/**
	 * 获取请求的参数，包含分页参数的初始化
	 * 
	 * @param request
	 * @return
	 */
	public static Map<Object, Object> getPageParameterMap(
			HttpServletRequest request) {
		Map<Object, Object> parameterMap = getParameterMap(request);
		return getPageParameterMap(parameterMap);
	}

	/**
	 * 获取分页参数
	 * 
	 * @param request
	 * @param page
	 *            页码
	 * @param rows
	 *            每页数据量的大小
	 * @return
	 */
	public static Map<Object, Object> getPageParameterMap(
			HttpServletRequest request, String page, String rows) {
		Map<Object, Object> parameterMap = getParameterMap(request);
		parameterMap.put("page", page);
		parameterMap.put("rows", rows);
		return getPageParameterMap(parameterMap);
	}

	/**
	 * 获取请求的参数，包含分页参数的初始化
	 * 
	 * @param request
	 * @return
	 */
	public static Map<Object, Object> getPageParameterMap(
			Map<Object, Object> parameterMap) {
		// 当前页码
		String page = parameterMap.containsKey("page") ? parameterMap.get(
				"page").toString() : null;
		// 每页显示数量
		String rows = parameterMap.containsKey("rows") ? parameterMap.get(
				"rows").toString() : null;
		if (StringUtil.isNotEmpty(page) && FrameUtil.isNumeric(page)) {
			int pg = Integer.valueOf(page);
			if (pg > 0) {
				parameterMap.put("page", Integer.valueOf(page));
			} else {
				parameterMap.put("page", 1);
			}
		} else {
			parameterMap.put("page", 1);
		}
		if (StringUtil.isNotEmpty(rows) && FrameUtil.isNumeric(rows)) {
			int rs = Integer.valueOf(rows);
			if (rs >= 1 && rs <= maxPageSize) {
				parameterMap.put("rows", rs);
			}
		} else {
			parameterMap.put("rows", PagerUtil.pageSize);
		}
		return parameterMap;
	}

	/**
	 * 获取请求的参数，如果参数中有分页的参数，则将其去掉
	 * 
	 * @param request
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static Map<Object, Object> getParameterMapNotPagerParam(
			HttpServletRequest request) {
		Map<Object, Object> parameterMap = new HashMap<Object, Object>();
		Enumeration<String> parameternames = request.getParameterNames();
		while (parameternames.hasMoreElements()) {
			String name = (String) parameternames.nextElement();
			parameterMap.put(name, request.getParameter(name));
		}
		parameterMap.remove("page");
		parameterMap.remove("rows");
		return parameterMap;
	}

	/**
	 * 获取用户请求的某个参数的值
	 * 
	 * @param name
	 * @return
	 */
	public static String getParameter(HttpServletRequest request, String name) {
		return request.getParameter(name);
	}

	/**
	 * 获取用户请求的某个参数的值列表(如果一个表单中元素的name有重复的)
	 * 
	 * @param name
	 * @return
	 */
	public static String[] getParameters(HttpServletRequest request, String name) {
		return request.getParameterValues(name);
	}

	/**
	 * 向客户端输出数据
	 * 
	 * @param message
	 * @throws Exception
	 */
	public static void outputMessage(HttpServletResponse response,
			String message) throws Exception {
		outputMessage(response, message, ContentTypeEnum.TEXT_HTML.getValue());
	}

	/**
	 * 将一个对象以json格式输出到客户端
	 * 
	 * @param object
	 * @throws Exception
	 */
	public static void outputJsonMessage(HttpServletResponse response,
			Object object) throws Exception {
		outputMessage(response, FrameUtil.json(object));
	}

	/**
	 * 判断当前请求是否是ajax请求,如果传入的参数isajax==1表示为ajax请求，其他非ajax请求
	 * 
	 * @return
	 */
	public static boolean isAjaxRequest(HttpServletRequest request) {
		return "1".equals(request.getParameter(ServletUtil.ISAJAX));
	}

	/**
	 * 获取jsonp中callback对于的函数名称
	 * 
	 * @param request
	 * @return
	 */
	public static String getJsonpCallFunName(HttpServletRequest request) {
		return request.getParameter(ServletUtil.JSONP_CALLBACK);
	}

	/**
	 * 下载文件
	 * 
	 * @param response
	 * @param fileName
	 *            文件名
	 * @param bs
	 *            文件数据
	 * @throws IOException
	 */
	public static void downLoadFile(HttpServletResponse response,
			String fileName, byte[] bs) throws IOException {
		response.reset();
		response.setContentType("application/octet-stream");

		response.setHeader("Content-Disposition", "attachment; filename="
				+ fileName);
		if (bs != null) {
			response.getOutputStream().write(bs);
		}
		response.getOutputStream().flush();
		response.getOutputStream().close();
	}

	/**
	 * 向客户端输出数据
	 * 
	 * @param message
	 * @throws Exception
	 */
	public static void outputMessage(HttpServletResponse response,
			String message, String contextType) throws IOException {
		response.setContentType(contextType);
		response.setCharacterEncoding("UTF-8");
		response.setHeader("Cache-Control", "no-cache");
		response.getWriter().write(message);
	}

	/**
	 * 将一个对象以json格式输出到客户端，支持jsonp格式
	 * 
	 * @param object
	 * @throws Exception
	 */
	public static void outputJsonMessage(HttpServletRequest request,
			HttpServletResponse response, Object object) throws IOException {
		String json = FrameUtil.json(object);
		String jsonpCallFunName = getJsonpCallFunName(request);
		outputMessage(
				response,
				StringUtil.isNotEmpty(jsonpCallFunName) ? String.format(
						"%s(%s)", jsonpCallFunName, json) : json,
				ContentTypeEnum.TEXT_PLAIN.getValue());
	}

	/**
	 * 判断request中的一个参数是否不为空
	 * 
	 * @param request
	 * @param paramName
	 * @return
	 */
	public static boolean isNotEmpty(HttpServletRequest request,
			String paramName) {
		return StringUtil.isNotEmpty(request.getParameter(paramName));
	}

	/**
	 * 判断request中的一个参数是否是一个数字。参数必须在request中存在，若不存在将出现异常
	 * 
	 * @param request
	 * @param paramName
	 * @return
	 */
	public static boolean isNumber(HttpServletRequest request, String paramName) {
		return FrameUtil.isNumeric(request.getParameter(paramName));
	}

	/**
	 * 将request中的数据绑定到指定的类型之上
	 * 
	 * @param <T>
	 * @param request
	 *            httprequest请求
	 * @param classType
	 *            需要将请求绑定到的数据模型的类型
	 * @return
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static <T extends Object> T bindRequestToModel(
			HttpServletRequest request, Class classType) {
		T model = (T) BeanUtils.instantiateClass(classType);
		new ServletRequestDataBinder(model).bind(request);
		return model;
	}

	public static int getSessionTimeOut() {
		if (sessionTimeFlag) {
			Object st = PropertiesCacheUtil.getValue(
					PropertiesFileEnum.CONST.getFilename(), SESSION_TIME_OUT);
			if (st != null) {
				sessionTimeOut = Integer.parseInt(st.toString());
			}
			sessionTimeFlag = false;
		}
		return sessionTimeOut;
	}

	/**
	 * 获取session中的所有键值
	 * 
	 * @param request
	 * @param response
	 * @return
	 */
	public static Map<String, Object> getSessionMap(HttpServletRequest request,
			HttpServletResponse response) {
		return getSessionService().getSessionMap(request, response);
	}

	/**
	 * @Title: getSessionAttribute
	 * @Description: 获取sesion中的key对应的值
	 * @param @param request
	 * @param @param response
	 * @param @param key
	 * @param @return 设定文件
	 * @return Object 返回类型
	 * @throws
	 */
	public static Object getSessionAttribute(HttpServletRequest request,
			HttpServletResponse response, String key) {
		return getSessionService().getAttribute(request, response, key);
	}

	public static Map<String, Object> getSessionMap(String sessionId) {
		return getSessionService().getSessionMap(sessionId);
	}

	/**
	 * 把对象放置到Session
	 * 
	 * @param request
	 * @param key
	 * @param obj
	 */
	public static void putSession(HttpServletRequest request,
			HttpServletResponse response, String key, Object obj) {
		getSessionService().putSession(request, response, key, obj);
	}

	/**
	 * 从Session中取对象
	 * 
	 * @param request
	 * @param key
	 * @return
	 */
	public static Object getSession(HttpServletRequest request,
			HttpServletResponse response, String key) {
		return getSessionService().getSession(request, response, key);
	}

	/**
	 * 从Session中删除对象
	 * 
	 * @param request
	 * @param key
	 */
	public static void removeSession(HttpServletRequest request,
			HttpServletResponse response, String key) {
		getSessionService().removeSession(request, response, key);
	}

	/**
	 * 获取sessionid
	 * 
	 * @param request
	 * @param response
	 * @return
	 */
	public static String getSessionId(HttpServletRequest request,
			HttpServletResponse response) {
		return getSessionService().getSessionId(request, response);
	}

	/**
	 * 初始化sessionId
	 * 
	 * @param request
	 * @param response
	 */
	public static void initSessionId(HttpServletRequest request,
			HttpServletResponse response) {
		getSessionService().initSessionId(request, response);
		getSessionService().flush(request, response);
	}

	/**
	 * 获取主域名(.yijiedai.com)
	 * 
	 * @return
	 */
	public static String domainHost() {
		return PropertiesCacheUtil.getValue(
				PropertiesFileEnum.WEB.getFilename(), "domainHost").toString();
	}

	/**
	 * 获取cookie
	 * 
	 * @param request
	 * @param cookieName
	 * @return
	 */
	public static Cookie getCookie(HttpServletRequest request, String cookieName) {
		if (StringUtil.isEmpty(cookieName)) {
			return null;
		}
		Cookie[] cookies = request.getCookies();
		if (cookies != null) {
			for (int i = 0; i < cookies.length; i++) {
				if (cookies[i].getName().equals(cookieName)) {
					return cookies[i];
				}
			}
		}
		return null;
	}

	/**
	 * 获取cookie的值
	 * 
	 * @param request
	 * @param cookieName
	 * @return
	 */
	public static String getCookieValue(HttpServletRequest request,
			String cookieName) {
		Cookie cookie = ServletUtil.getCookie(request, cookieName);
		return cookie == null ? null : cookie.getValue();
	}

	/**
	 * 删除cookie
	 * 
	 * @param request
	 * @param response
	 * @param cookieName
	 */
	public static void deleteCookie(HttpServletRequest request,
			HttpServletResponse response, String cookieName) {
		Cookie cookie = getCookie(request, cookieName);
		if (cookie != null) {
			addCookie(response, cookieName, cookie.getValue(), 0,
					cookie.getDomain(), cookie.getPath());
		}
	}

	/**
	 * 添加cookie
	 * 
	 * @param response
	 * @param name
	 *            cookie名称
	 * @param value
	 *            cookie值
	 * @param maxAge
	 *            有效时间（秒）
	 * @param domain
	 *            域
	 * @param path
	 *            cookie的path
	 */
	public static void addCookie(HttpServletResponse response, String name,
			String value, Integer maxAge, String domain, String path) {
		Cookie cookie = new Cookie(name, value);
		if (StringUtil.isNotEmpty(domain)) {
			cookie.setDomain(domain);
		}
		if (StringUtil.isNotEmpty(path)) {
			cookie.setPath(path);
		} else {
			cookie.setPath("/");
		}
		if (maxAge != null) {
			cookie.setMaxAge(maxAge);
		}
		response.addCookie(cookie);
	}

	/**
	 * 放入cookie
	 * 
	 * @param response
	 * @param name
	 *            cookie的name
	 * @param value
	 *            值
	 * @param useHost
	 *            是否使用主域名
	 */
	public static void addCookie(HttpServletResponse response, String name,
			String value, boolean useHost) {
		String domain = useHost ? domainHost() : null;
		addCookie(response, name, value, null, domain, null);
	}

	/**
	 * 清除session所有数据
	 * 
	 * @param request
	 * @param response
	 * @param isRemoveSessionId
	 *            是否移除sessionid
	 */
	public static void cleanAllSession(HttpServletRequest request,
			HttpServletResponse response, boolean isRemoveSessionId) {
		getSessionService().cleanAllSession(request, response,
				isRemoveSessionId);
	}

	public static ISessionService getSessionService() {
		if (SessionTypeEnum.WEBSESSION.name().equals(
				FrameUtil.getConstResource("SESSION_TYPE"))) {
			return SessionServiceFactory
					.getSessionService(SessionTypeEnum.WEBSESSION);
		} else {
			return SessionServiceFactory
					.getSessionService(SessionTypeEnum.CLUSTERSESSION);
		}
	}

	/**
	 * 返回用户的IP地址
	 * 
	 * @param request
	 * @return
	 */
	public static String getIpAddr(HttpServletRequest request) {
		String ip = request.getHeader("X-Forwarded-For");
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("WL-Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("HTTP_CLIENT_IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("HTTP_X_FORWARDED_FOR");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getRemoteAddr();
		}
		return ip;
	}

	/**
	 * @Title: getRootPath
	 * @Description: 获取请求的跟路径
	 * @param @return 设定文件
	 * @return String 返回类型
	 * @throws
	 */
	public static String getRootPath() {
		return FrameUtil.getResourceByFile(
				PropertiesFileEnum.WEB.getFilename(), "rootPath");
	}

	/**
	 * 获取springmvc请求的后缀
	 * 
	 * @return
	 */
	public static String getUrlStuff() {
		return PropertiesCacheUtil.getValue(
				Constant.PropertiesFileEnum.WEB.getFilename(), URLSTUFFKEY)
				.toString();
	}

	/**
	 * 获取完整的url
	 * 
	 * @param url
	 * @param paramMap
	 * @return
	 */
	public static String getUrl(String url, Map<String, Object> paramMap) {
		StringBuffer s = new StringBuffer();
		s.append(getRootPath()).append(url).append(getUrlStuff());
		if (paramMap != null && paramMap.size() >= 1) {
			s.append("?");
			int i = 0;
			for (Entry<String, Object> param : paramMap.entrySet()) {
				s.append(param.getKey())
						.append("=")
						.append(StringUtil.convertObjToString(param.getValue()))
						.append((i < paramMap.size() - 1) ? "&" : "");
			}
		}
		return s.toString();
	}

	public static String getReferer(HttpServletRequest request) {
		return request.getHeader("Referer");
	}

	/**
	 * 获取完整的url
	 * 
	 * @param url
	 * @return
	 */
	public static String getUrl(String url) {
		return getUrl(url, null);
	}

}
